#ifndef __WIZ_LOCK_HPP__SHANHAOBO_19800429__
#define __WIZ_LOCK_HPP__SHANHAOBO_19800429__

#include "./WizMutex.hpp"
#include "./WizAtomicCount.hpp"

namespace Wiz
{
    namespace Lock
    {
        class WIZ_EXPORT Type
        {
            ::Wiz::Mutex::Ptr m_Core;
        public:
            Type()
            {
                this->m_Core = ::Wiz::Mutex::Create();
                WIZ_ASSERT(::Wiz::IsValidPtr(this->m_Core));
            }
            ~Type()
            {
                ::Wiz::Mutex::Destroy(this->m_Core);
            }
        public:
            ::Wiz::Void::Type Lock()
            {
                this->m_Core->Acquire();
            }
            ::Wiz::Void::Type UnLock()
            {
                this->m_Core->Release();
            }
            ::Wiz::Bool::Type TryLock()
            {
                return this->m_Core->TryAcquire();
            }
        };
        WIZ_DECLARE(::Wiz::Lock::Type);
    } /// end of namespace Lock

    namespace ScopedLock
    {
        class Type
        {
            ::Wiz::Lock::Ref m_Lock;
        public:
            Type(::Wiz::Lock::Ref lck) : m_Lock(lck)
            {
                m_Lock.Lock();
            }
            ~Type()
            {
                m_Lock.UnLock();
            }
        };
    } /// end of namespace ScopedLock

    namespace ReadWriteLock
    {
        class Type
        {
            ::Wiz::Lock::Type           m_WriteLock;
            ::Wiz::AtomicCount::Ptr     m_ReadACPtr;
        public:
            Type()
            {
                m_ReadACPtr = ::Wiz::AtomicCount::Create();
            };
            ~Type()
            {
                ::Wiz::AtomicCount::Destroy(m_ReadACPtr);
            }
        public:
            ::Wiz::Void::Type BeginRead()
            {
                while (m_WriteLock.TryLock() == ::Wiz::Bool::False)
                {
                    ::Wiz::Int::Type tmp = m_ReadACPtr->Count();
                    if (tmp == 0)
                    {
                        continue;
                    }
                    if (m_ReadACPtr->CompareSwap(tmp, tmp + 1) == tmp)
                    {
                        return;
                    }
                }
                m_ReadACPtr->CASInc();
            }

            ::Wiz::Void::Type EndRead()
            {
                if (m_ReadACPtr->DecIsZero())
                {
                    m_WriteLock.UnLock();
                }
            }

            ::Wiz::Void::Type BeginWrite()
            {
                m_WriteLock.Lock();
            }

            ::Wiz::Void::Type EndWrite()
            {
                m_WriteLock.UnLock();
            }
        };
    } /// end of namespace ReadWriteLock
} /// end of namespace Wiz

#endif /*__WIZ_LOCK_HPP__SHANHAOBO_19800429__*/
